package com.apes.scm.rbac.model;

import com.alibaba.fastjson.annotation.JSONField;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;
import org.springframework.util.StringUtils;

import javax.persistence.*;
import java.util.*;

/**
 * 功能：通用角色
 *
 * @author xul
 * @create 2018-03-15 16:00
 */
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = Role.CONST_TABLE_NAME)
public class Role extends Model {
    public static final String CONST_TABLE_NAME = "aut_role";

    @Id
    @Column(name = "id")
    @ApesGenerator(code = CONST_TABLE_NAME, name = "角色")
    private String id;

    @Column(name = "name")
    private String name;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "role_type_id", referencedColumnName = "id")
    private Enumeration roleType; //角色类型（ENUMERATION_TYPE_ID 为 hrRoleType）

    /**
     * These are the members assined to this role. Initially this would be an
     * empty collection.
     */
    @ManyToMany(cascade = {CascadeType.MERGE},mappedBy = "roles",fetch = FetchType.LAZY)
    private Set<Post> assignedPosts;

    /**
     * These are all direct descendants of this role.
     */
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "aut_role_inheritance",
            joinColumns = {@JoinColumn(name = "role_parent", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "role_child", referencedColumnName = "id")})
    private Set<Role> descendants;

    /**
     * These are all direct ascendants of this role.
     */
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "aut_role_inheritance",
            joinColumns = {@JoinColumn(name = "role_child", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "role_parent", referencedColumnName = "id")})
    private Set<Role> ascendants;


    @JSONField(serialize = false)
    @ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE}, fetch = FetchType.LAZY)
    @JoinTable(name = "aut_role_operation",
            joinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "operation_id", referencedColumnName = "operation_id"),
                    @JoinColumn(name = "menu_id", referencedColumnName = "menu_id")},
            indexes = {@Index(name = "idx_role_operation_menu_id", columnList = "menu_id, operation_id")}
    )
    private Set<Operation> operations;


    /*//排序
    public Set<Operation> getOperations(){
        Set<Operation> operationTreeSet = new TreeSet<Operation>(new OperationsComparator());
        if(operations != null) {
            operations.forEach(
                    (operation) -> {
                        operationTreeSet.add(operation);
                    }
            );
        }
        return operationTreeSet;
    }
    */


    /*前端界面对应操作列表*/
    @Transient
    private Set<Map> optList;

    /* 强行写死的前端界面对应操作列表(与终端枚举直接对应，枚举值增减 此处也需开发手动加上) */
    /**
    商户App
     */
    @Transient
    private Set<Map> merchantAppOptList;
    /**
    商户后台
     */
    @Transient
    private Set<Map> merchantSystemOptList;
    /**
    平台App
     */
    @Transient
    private Set<Map> platformAppOptList;
    /**
   平台后台
     */
    @Transient
    private Set<Map> platformSystemOptList;

    /**
     供应商平台
     */
    @Transient
    private Set<Map> supplierSystemOptList;

    @Transient
    public List<Menu> findMenus(String terminal) {
        Map<Integer, Menu> menus = new HashMap<>();
        getOperations().forEach(operation -> {
            Menu menu = operation.getMenu();
            Map<String, Operation> authOperations = menu.getAuthOperations();
            if (authOperations == null) authOperations = new HashMap<>();
            if (!authOperations.containsKey(operation.getOperationId())) {
                String topic = "event:wf.checkFormApiExist";
                Map body = MapUtil.mapper("formId", operation.getMenu().getLink(), "esbId", operation.getApi());
                Boolean exist = (Boolean) EventUtil.sendSynEvent(this, topic, body).stream().findFirst().orElse(false);
                if (!exist) {
                    authOperations.put(operation.getOperationId(), operation);
                }
            }
            Integer menuId = menu.getId();
            if (!menus.containsKey(menuId) && (StringUtils.isEmpty(terminal) || menu.getTerminalType().getId().equalsIgnoreCase(terminal)) && menu.isValid()) {
                menus.put(menuId, menu);
            }
        });
        return new ArrayList(menus.values());
    }


    /**
     * A role is equal with another role only by equality of name
     * or primary key.
     */
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Role) {
            Role role = Role.class.cast(obj);
            return role.getId() == this.getId();
        }
        return super.equals(obj);
    }
}
